package com.gitee.qdbp.vmall.sales.biz.goods.manage.service;

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.system.model.IAccount;
import com.gitee.qdbp.tools.utils.DateTools;
import com.gitee.qdbp.tools.utils.VerifyTools;
import com.gitee.qdbp.vmall.sales.api.goods.main.model.GoodsSkuRefBean;
import com.gitee.qdbp.vmall.sales.api.goods.main.model.GoodsSkuRefWhere;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.SalesSummingBean;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.SalesSummingUpdate;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.SalesSummingWhere;
import com.gitee.qdbp.vmall.sales.biz.goods.main.basic.GoodsSkuRefBasic;
import com.gitee.qdbp.vmall.sales.biz.goods.manage.basic.SalesSummingBasic;
import com.gitee.qdbp.vmall.sales.biz.goods.manage.model.AddSalesQuantityParams;
import com.gitee.qdbp.vmall.sales.enums.SumType;

/**
 * 销量汇总业务处理类
 *
 * @author zhh
 * @version 170812
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public class SalesSummingExecutor {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(SalesSummingExecutor.class);

    @Autowired
    private GoodsSkuRefBasic goodsSkuRefBasic;
    @Autowired
    private SalesSummingBasic salesSummingBasic;

    /** 增加销量, 如果是虚拟销量, 只增加总销量 **/
    public void add(AddSalesQuantityParams params, IAccount operator) throws ServiceException {
        String msg = "Failed to add GoodsSalesQuantity. ";

        if (VerifyTools.isBlank(params.getSkuId())) {
            log.error(msg + "params is null: SkuId");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(params.getQuantity())) {
            log.error(msg + "params is null: Quantity");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (params.getQuantity() == 0) {
            return; // 数量没变化, 不需要更新
        }

        updateOrInsert(params, SumType.ALL);
        if (!params.isFictitious()) {
            updateOrInsert(params, SumType.YEAR);
            updateOrInsert(params, SumType.MONTH);
            updateOrInsert(params, SumType.WEEK);
            updateOrInsert(params, SumType.DAY);
        }
    }

    private void updateOrInsert(AddSalesQuantityParams params, SumType type) throws ServiceException {
        SalesSummingUpdate up = toSalesSummingBean(params, type);
        // 向vml_sales_summing表插入记录
        int rows = salesSummingBasic.update(up, false);
        if (rows == 0) { // 更新记录数为0, 说明记录不存在, 新增一条记录
            String goodsUid;
            {
                GoodsSkuRefWhere where = new GoodsSkuRefWhere();
                where.setSkuId(params.getSkuId());
                GoodsSkuRefBean ref = goodsSkuRefBasic.find(where);
                if (ref == null) { // 没有单品信息, 说明是单一商品, SkuId=GoodsUid
                    goodsUid = params.getSkuId();
                } else {
                    goodsUid = ref.getGoodsUid();
                }
            }
            SalesSummingBean bean = up.getWhere().to(SalesSummingBean.class);
            bean.setGoodsUid(goodsUid);
            bean.setSalesQuantity(params.getQuantity());
            try {
                salesSummingBasic.create(bean);
            } catch (ServiceException e) {
                // 如果违反唯一约束, 有可能别的线程已经新增了, 再更新一次
                if (ResultCode.DB_DUPLICATE_KEY.getCode().equals(e.getCode())) {
                    salesSummingBasic.update(up, true);
                } else {
                    throw e;
                }
            }
        }
    }

    private SalesSummingUpdate toSalesSummingBean(AddSalesQuantityParams params, SumType type) {
        SalesSummingUpdate ud = new SalesSummingUpdate();
        ud.setSalesQuantityAdd(params.getQuantity());
        SalesSummingWhere w = ud.getWhere(true);
        w.setTenantCode(params.getTenantCode());
        w.setSkuId(params.getSkuId());
        w.setSumType(type);
        w.setTimeRange(calcTimeRange(type, params.getSalesTime()));
        return ud;
    }

    private int calcTimeRange(SumType type, Date time) {
        switch (type) {
        case YEAR:
            return DateTools.getYear(time);
        case MONTH:
            return DateTools.getYear(time) * 100 + DateTools.getMonth(time) + 1;
        case WEEK:
            return DateTools.getYear(time) * 100 + DateTools.getWeekOfYear(time);
        case DAY:
            return DateTools.getYear(time) * 10000 + DateTools.getMonth(time) * 100 + DateTools.getDay(time);
        default:
            return 0;
        }
    }
}
